#ifndef RESPIRATORY_RATE_CALCULATOR_H
#define RESPIRATORY_RATE_CALCULATOR_H

#include <vector>
#include <queue>
#include <list>
#include <algorithm>
#include <limits>

class RespiratoryRateCalculator {
public:
    // Singleton instance access
    static RespiratoryRateCalculator& getInstance();
    
    // Data structure to hold peak information
    struct NumberPair {
        int intValue;
        double doubleValue;
        NumberPair(int i, double d) : intValue(i), doubleValue(d) {}
    };
    
    // Add new ECG data and process it
    void addData(double ecgValue, int sampleIndex);
    
    // Get the current heart rate
    double getHeartRate() const { return heartRate; }
    // Get the current respiratory rate
    double getRespiratoryRate() const { return resp; }
    
private:
    // Private constructor for singleton
    RespiratoryRateCalculator();
    
    // Constants
    static const int requiredPeaks = 16;  // Need 16 R-peaks to calculate respiratory rate
    static const int FR = 256;           // Sampling rate 256Hz
    static const double refractoryPeriodSec; // R-peak refractory period (seconds)
    const int refractoryPeriodSamples;    // Refractory period in samples
    
    // Member variables
    std::queue<int> rPeakTimestamps;     // Stores R-peak timestamps (sample indices)
    std::queue<double> rPeakTimestampsValues; // Stores R-peak values
    int lastPeakIndex;                   // Last R-peak position
    std::vector<double> ecgBuffer;       // Stores ECG data for R-peak detection
    double heartRate;                    // Current heart rate
    double resp;                         // Current respiratory rate
    double previousRate;                 // Previous respiratory rate for constraints
    
    // R-peak detection methods
    std::vector<NumberPair> findRPeaks(const std::vector<double>& ecgData);
    
    // Respiratory rate calculation
    double findRespPeaks(const std::queue<int>& queue1, const std::queue<double>& queue2);
    
    // Helper functions
    double getMaxValue(const std::vector<double>& ecgData) const;
    double applyPhysiologicalConstraints(double rate);
    
    // Delete copy constructor and assignment operator for singleton
    RespiratoryRateCalculator(const RespiratoryRateCalculator&) = delete;
    RespiratoryRateCalculator& operator=(const RespiratoryRateCalculator&) = delete;
};

#endif // RESPIRATORY_RATE_CALCULATOR_H